#include <iostream>
#include "db_manager/connect_pool/connect_pool.h"
#include <cstring>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>

// 信号处理函数 - 用于优雅地关闭服务器
void signal_handler(int signum)
{
    // 输出收到的信号信息
    std::cout << "Received signal " << signum << ", shutting down..." << std::endl;
    // 设置运行标志为false，触发服务器关闭流程
    is_running = false;
}

int main()
{
    Config &config = Config::getInstance();
#ifdef _WIN32
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        std::cerr << "WSAStartup failed" << std::endl;
        return 1;
    }
    SOCKET server_fd = INVALID_SOCKET; // 服务器套接字（Windows使用SOCKET类型）
#elif defined(__linux__)
    // 服务器套接字文件描述符
    int server_fd;
#endif
    // 用于存储服务器地址信息的结构体
    struct sockaddr_in address;
    // 用于设置socket选项的变量
    int opt = 1;
    // 地址结构体的长度
    int addrlen = sizeof(address);

    // 注册信号处理函数，捕获SIGINT(Ctrl+C)和SIGTERM(终止信号)
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);

// 创建服务器套接字
// AF_INET表示使用IPv4协议
// SOCK_STREAM表示使用TCP协议
// 0表示使用默认的协议
#ifdef _WIN32
    // 创建服务器套接字
    // AF_INET: 使用IPv4协议 | SOCK_STREAM: 使用TCP协议 | IPPROTO_TCP: 明确指定TCP协议
    server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (server_fd == INVALID_SOCKET)
    { // Windows中套接字无效时返回INVALID_SOCKET
        std::cerr << "socket failed: " << WSAGetLastError() << std::endl;
        WSACleanup(); // 清理Winsock资源
        return 1;
    }

    // 设置socket选项（允许重用端口和地址）
    // SOL_SOCKET: 操作socket层选项 | SO_REUSEADDR: 允许重用本地地址
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) == SOCKET_ERROR)
    {
        std::cerr << "setsockopt failed: " << WSAGetLastError() << std::endl;
        closesocket(server_fd); // Windows关闭套接字用closesocket
        WSACleanup();
        return 1;
    }
#elif defined(__linux__)
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        // 如果创建失败，输出错误信息并退出
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // 设置socket选项
    // SOL_SOCKET表示操作socket层的选项
    // SO_REUSEADDR允许重用本地地址和端口
    // SO_REUSEPORT允许多个套接字绑定到同一个端口
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
    {
        // 如果设置失败，输出错误信息并退出
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
#endif

    // 配置服务器地址信息
    address.sin_family = AF_INET;                            // 使用IPv4协议
    address.sin_addr.s_addr = INADDR_ANY;                    // 监听所有可用的网络接口
    address.sin_port = htons(config.GetValue("port", 7092)); // 设置端口号，htons将主机字节序转换为网络字节序
#ifdef _WIN32
    // 绑定套接字到指定端口
    if (::bind(server_fd, (struct sockaddr *)&address, sizeof(address)) == SOCKET_ERROR)
    {
        std::cerr << "bind failed: " << WSAGetLastError() << std::endl;
        closesocket(server_fd);
        WSACleanup();
        return 1;
    }

    // 开始监听端口（等待队列长度为5）
    if (listen(server_fd, 5) == SOCKET_ERROR)
    {
        std::cerr << "listen failed: " << WSAGetLastError() << std::endl;
        closesocket(server_fd);
        WSACleanup();
        return 1;
    }
#elif defined(__linux__)
    // 将套接字绑定到指定的地址和端口
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
    {
        // 如果绑定失败，输出错误信息并退出
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 开始监听端口，第二个参数是等待连接队列的最大长度
    if (listen(server_fd, 5) < 0)
    {
        // 如果监听失败，输出错误信息并退出
        perror("listen");
        exit(EXIT_FAILURE);
    }
#endif

    // 输出服务器启动信息
    std::cout << "Server listening on port " << config.GetValue("port", 7092) << std::endl;

    // 创建连接池实例，最大连接数为MAX_CONNECTIONS
    ConnectionPool pool;
#ifdef _WIN32
    // 循环接受客户端连接，直到服务器停止运行
    while (is_running)
    {

        SOCKET new_socket = INVALID_SOCKET; // 客户端套接字
        // 设置服务器套接字为非阻塞模式（Windows使用ioctlsocket）
        u_long mode = 1; // 1表示非阻塞模式，0表示阻塞模式
        if (ioctlsocket(server_fd, FIONBIO, &mode) == SOCKET_ERROR)
        {
            std::cerr << "ioctlsocket failed: " << WSAGetLastError() << std::endl;
            break;
        }
        // 接受客户端连接（非阻塞模式下无连接时会返回错误）
        new_socket = accept(server_fd, (struct sockaddr *)&address, (int *)&addrlen);

        // 处理连接接受结果
        if (new_socket == INVALID_SOCKET)
        {
            int err = WSAGetLastError();
            // 非阻塞模式下无连接请求时的正常错误，忽略并继续等待
            if (err == WSAEWOULDBLOCK)
            {
                Sleep(100); // Windows休眠函数（单位：毫秒）
                continue;
            }
            else
            {
                // 其他错误情况（如服务器关闭）
                std::cerr << "accept failed: " << err << std::endl;
                break;
            }
        }

        // 将新连接添加到连接池
        if (!pool.add_connection(new_socket))
        {
            std::cerr << "Connection pool is full, rejecting new connection" << std::endl;
            const char *msg = "Server is busy, please try again later";
            send(new_socket, msg, strlen(msg), 0); // 发送忙信号
            closesocket(new_socket);               // 关闭客户端套接字
        }
    }
    // 清理资源（服务器停止时）
    closesocket(server_fd); // 关闭服务器套接字
    WSACleanup();           // 清理Winsock库资源
#elif defined(__linux__)
    while (is_running)
    {

        int new_socket = 0;
        // 将服务器套接字设置为非阻塞模式
        // 这样accept()会立即返回，而不是阻塞等待连接
        fcntl(server_fd, F_SETFL, O_NONBLOCK);
        // 接受客户端连接
        new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen);

        // 检查接受连接的结果
        if (new_socket < 0)
        {
            // 如果是因为没有连接请求而失败，短暂休眠后继续循环
            if (errno == EAGAIN || errno == EWOULDBLOCK)
            {
                usleep(100000); // 休眠100毫秒
                continue;
            }
            else
            {
                // 其他错误情况，输出错误信息并退出循环
                perror("accept");
                break;
            }
        }
        // 尝试将新连接添加到连接池
        if (!pool.add_connection(new_socket))
        {
            // 如果连接池已满，向客户端发送忙信号并关闭连接
            std::cerr << "Connection pool is full, rejecting new connection" << std::endl;
            const char *msg = "Server is busy, please try again later";
            send(new_socket, msg, strlen(msg), 0);
            close(new_socket);
        }
    }
    // 关闭服务器套接字
    close(server_fd);
#endif

    // 输出服务器停止信息
    std::cout << "Server stopped" << std::endl;

    return 0;
}